package com.atguigu.spring.aop.xml;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * ①作用
 * ②语法细节
 * 用*号代替“权限修饰符”和“返回值”部分表示“权限修饰符”和“返回值”不限
 * 在包名的部分，一个“*”号只能代表包的层次结构中的一层，表示这一层是任意的。
 * 例如：*.Hello匹配com.Hello，不匹配com.atguigu.Hello
 * 在包名的部分，使用“*..”表示包名任意、包的层次深度任意
 * 在类名的部分，类名部分整体用*号代替，表示类名任意
 * 在类名的部分，可以使用*号代替类名的一部分
 * 例如：*Service匹配所有名称以Service结尾的类或接口
 * 在方法名部分，可以使用*号表示方法名任意
 * 在方法名部分，可以使用*号代替方法名的一部分
 * 例如：*Operation匹配所有方法名以Operation结尾的方法
 * 在方法参数列表部分，使用(..)表示参数列表任意
 * 在方法参数列表部分，使用(int,..)表示参数列表以一个int类型的参数开头
 * 在方法参数列表部分，基本数据类型和对应的包装类型是不一样的
 * 切入点表达式中使用 int 和实际方法中 Integer 是不匹配的
 * 在方法返回值部分，如果想要明确指定一个返回值类型，那么必须同时写明权限修饰符
 * 例如：execution(public int ..Service.*(.., int)) 正确
 * 例如：execution(* int ..Service.*(.., int)) 错误
 * 3.4.6、重用切入点表达式
 *
 * ①声明
 * ②在同一个切面中使用
 * ③在不同切面中使用
 */

@Component  //标识为普通组件
public class LogAspect {
    public void beforeMethod(JoinPoint joinPoint){
        String name = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        System.out.println("Logger-->前置通知，方法名："+name+",参数是："+ Arrays.toString(args));
    }
    public void afterMethod(JoinPoint joinPoint){
        String name = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        System.out.println("Logger-->后置通知，方法名："+name+",参数是："+ Arrays.toString(args));
    }

    public void afterReturningMethod(JoinPoint joinPoint,Object result){
        String name = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        System.out.println("Logger-->返回通知,方法名："+name+",参数是："+ Arrays.toString(args)+",结果是："+result);
    }

    public void afterThrowingMethod(JoinPoint joinPoint, Throwable ex){
        String name = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        System.out.println("Logger-->异常通知,方法名："+name+",参数是："+ Arrays.toString(args)+",异常信息是："+ex);
    }

    public Object aroundMethod(ProceedingJoinPoint joinPoint){
        String name = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        Object result=null;
        try{
            System.out.println("环绕通知：前置通知");
            result = joinPoint.proceed();
            System.out.println("环绕通知：返回通知");
        }catch (Throwable e) {
            e.printStackTrace();
            System.out.println("环绕通知：异常通知");
        } finally {
            System.out.println("环绕通知：后置通知");
        }
        return result;
    }
}
